package com.ken.litespring.beans.factory.support;

import com.ken.litespring.beans.BeanDefinition;
import com.ken.litespring.beans.factory.BeanFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author liushiyu@changingedu.com
 * @date 3/4/2020 下午5:08
 */
public class DefaultBeanFactory implements BeanFactory {

    public static final String ID_ATTRIBUTE = "id";

    public static final String CLASS_ATTRIBUTE = "class";

    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

    public DefaultBeanFactory(String configFile) {
        this.loadBeanDefinition(configFile);
    }

    /**
     * 加载bean的配置
     * @param configFile
     */
    private void loadBeanDefinition(String configFile){
        Document document = null;
        SAXReader saxReader = new SAXReader();
        ClassLoader cl = this.getClassLoader();
        try {
            document = saxReader.read(cl.getResourceAsStream(configFile));
            Element rootElement = document.getRootElement(); // <beans>
            Iterator<Element> elementIterator = rootElement.elementIterator();
            while (elementIterator.hasNext()) {
                Element element = elementIterator.next();// <bean>
                String id = element.attributeValue(ID_ATTRIBUTE);
                String beanClassName = element.attributeValue(CLASS_ATTRIBUTE);
                BeanDefinition bd = new GenericBeanDefinition(id, beanClassName);
                beanDefinitionMap.put(id, bd);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    public BeanDefinition getBeanDefinition(String beanId) {
        return this.beanDefinitionMap.get(beanId);
    }

    public Object getBean(String beanId) throws Exception {
        // 根据beanId获取bean的定义
        BeanDefinition beanDefinition = this.getBeanDefinition(beanId);
        if (beanDefinition == null) {
            return null;
        }
        String beanClassName = beanDefinition.getBeanClassName();
        // 获取classLoader
        ClassLoader cl = this.getClassLoader();
        // 根据类名实例化bean
        Class<?> clz = cl.loadClass(beanClassName);
        return clz.newInstance();
    }

    /**
     * 获取 ClassLoader
     * @return
     */
    private ClassLoader getClassLoader(){
        ClassLoader cl = null;
        if (cl == null) {
            // getClassLoader() returning null indicates the bootstrap ClassLoader
            try {
                cl = ClassLoader.getSystemClassLoader();
            } catch (Throwable ex) {
                // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
            }
        }
        return cl;
    }
}
